import jwt
from flask import Blueprint, jsonify, request, session, make_response
from models import User, db, PatientTable

import csv
from io import StringIO

patient_api = Blueprint('patient_api', __name__)


# 获取挂号医院比例和挂号医院排行
@patient_api.route('/getDistributionOfHospital', methods=['GET'])
def get_distribution_of_hospital():
    patient_list = PatientTable.query.all()

    # 获取所有不同的挂号医院
    hospitals = PatientTable.query.with_entities(PatientTable.patient_hospital).distinct().all()

    # 初始化结果字典
    hospital_count = {dept[0]: 0 for dept in hospitals}

    total_count = 0

    for patient in patient_list:
        # 确保挂号医院在结果字典中
        if patient.patient_hospital in hospital_count:
            hospital_count[patient.patient_hospital] += 1
            total_count += 1

    # 计算挂号医院比例
    hospital_proportion = [
        {
            'name': hospital,
            'value': count
        }
        for hospital, count in hospital_count.items()
    ]

    # 按挂号数量排序
    hospital_ranking = sorted(hospital_count.items(), key=lambda x: x[1], reverse=True)

    # 将排序结果转换为列表格式
    hospital_ranking_list = [
        {
            'name': hospital,
            'value': count
        }
        for hospital, count in hospital_ranking
    ]

    data = {
        'code': 200,
        'data': {
            'proportion': hospital_proportion,
            'ranking': hospital_ranking_list
        }
    }
    return jsonify(data)


# 获取男女分布比例
@patient_api.route('/getDistributionOfSex', methods=['GET'])
def get_distribution_of_sex():
    patient_list = PatientTable.query.all()

    # 使用字典来存储计数
    sex_count = {'男': 0, '女': 0}

    for patient in patient_list:
        # 确保性别字段值是预期的
        if patient.patient_sex in sex_count:
            sex_count[patient.patient_sex] += 1

    # 将字典转换为列表格式
    result = [
        {
            'name': '男',
            'value': sex_count.get('男', 0)
        },
        {
            'name': '女',
            'value': sex_count.get('女', 0)
        }
    ]

    data = {'code': 200, 'data': result}
    return jsonify(data)


# 获取挂号类型比例和挂号类型排行
@patient_api.route('/getDistributionOfDepartment', methods=['GET'])
def get_distribution_of_department():
    patient_list = PatientTable.query.all()

    # 获取所有不同的挂号类型
    departments = PatientTable.query.with_entities(PatientTable.patient_department).distinct().all()

    # 初始化结果字典
    department_count = {dept[0]: 0 for dept in departments}

    total_count = 0

    for patient in patient_list:
        # 确保挂号类型在结果字典中
        if patient.patient_department in department_count:
            department_count[patient.patient_department] += 1
            total_count += 1

    # 计算挂号类型比例
    department_proportion = [
        {
            'name': department,
            'value': count
        }
        for department, count in department_count.items()
    ]

    # 按挂号数量排序
    department_ranking = sorted(department_count.items(), key=lambda x: x[1], reverse=True)

    # 将排序结果转换为列表格式
    department_ranking_list = [
        {
            'name': department,
            'value': count
        }
        for department, count in department_ranking
    ]

    data = {
        'code': 200,
        'data': {
            'proportion': department_proportion,
            'ranking': department_ranking_list
        }
    }
    return jsonify(data)


# 获取所有病人的身高数据
@patient_api.route('/get_patient_height_stats', methods=['GET'])
def get_patient_height_stats():
    patient_heights = PatientTable.query.with_entities(PatientTable.patient_height).all()

    # 提取身高数据列表
    heights = [height[0] for height in patient_heights]

    # 计算最高身高、最低身高和平均身高
    max_height = max(heights)
    min_height = min(heights)
    avg_height = sum(heights) / len(heights)

    result = [
        {
            'value': avg_height,
            'name': '平均身高'
        },
        {
            'value': max_height,
            'name': '最高身高'
        },
        {
            'value': min_height,
            'name': '最低身高'
        }
    ]
    data = {
        'code': 200,
        'data': result
    }

    # 返回结果
    return jsonify(data)


# 获取所有病人的体重数据
@patient_api.route('/get_patient_weight_stats', methods=['GET'])
def get_patient_weight_stats():
    patient_weights = PatientTable.query.with_entities(PatientTable.patient_weight).all()

    # 提取体重数据列表
    weights = [weight[0] for weight in patient_weights]

    # 计算最高体重、最低体重和平均体重
    max_weight = max(weights)
    min_weight = min(weights)
    avg_weight = sum(weights) / len(weights)

    result = [
        {
            'value': avg_weight,
            'name': '平均体重'
        },
        {
            'value': max_weight,
            'name': '最高体重'
        },
        {
            'value': min_weight,
            'name': '最低体重'
        }
    ]
    data = {
        'code': 200,
        'data': result
    }

    # 返回结果
    return jsonify(data)


# 获取所有病人的年龄数据
@patient_api.route('/get_patient_age_stats', methods=['GET'])
def get_patient_age_stats():
    patient_ages = PatientTable.query.with_entities(PatientTable.patient_age).all()

    # 提取体重数据列表
    ages = [age[0] for age in patient_ages]

    # 计算最高年龄、最低年龄和平均年龄
    max_ages = max(ages)
    min_ages = min(ages)
    avg_ages = sum(ages) / len(ages)

    result = [
        {
            'value': avg_ages,
            'name': '平均年龄'
        },
        {
            'value': max_ages,
            'name': '最高年龄'
        },
        {
            'value': min_ages,
            'name': '最低年龄'
        }
    ]
    data = {
        'code': 200,
        'data': result
    }

    # 返回结果
    return jsonify(data)


# 获取总人数
@patient_api.route('/get_patient_total', methods=['GET'])
def get_patient_total():
    total = PatientTable.query.count()
    data = {
        'code': 200,
        'data': total
    }

    # 返回结果
    return jsonify(data)


# 获取病患id与patient_id列表
@patient_api.route('/get_patient_list', methods=['GET'])
def get_patient_list():
    patients = PatientTable.query.all()

    patients_list = [
        {
            'id': patient.id,
            'patient_id': patient.patient_id,
            'patient_name': patient.patient_name,
            'patient_sex': patient.patient_sex,
            'patient_age': patient.patient_age,
            'patient_height': patient.patient_height,
            'patient_weight': patient.patient_weight,
            'patient_time': patient.patient_time.strftime('%Y-%m-%d %H:%M'),
            'patient_department': patient.patient_department,
            'patient_type': patient.patient_type,
            'patient_hospital': patient.patient_hospital
        }
        for patient in patients
    ]

    data = {
        'code': 200,
        'data': patients_list
    }

    # 返回结果
    return jsonify(data)


# 编辑病患信息
@patient_api.route('/edit_patient/<int:patient_id>', methods=['PUT'])
def edit_patient(patient_id):
    patient = PatientTable.query.get(patient_id)
    if not patient:
        return jsonify({'error': 'Patient not found'}), 404

    data = request.get_json()
    patient.patient_name = data.get('patient_name', patient.patient_name)
    patient.patient_sex = data.get('patient_sex', patient.patient_sex)
    patient.patient_age = data.get('patient_age', patient.patient_age)
    patient.patient_height = data.get('patient_height', patient.patient_height)
    patient.patient_weight = data.get('patient_weight', patient.patient_weight)
    patient.patient_time = data.get('patient_time')
    patient.patient_department = data.get('patient_department', patient.patient_department)
    patient.patient_type = data.get('patient_type', patient.patient_type)
    patient.patient_hospital = data.get('patient_hospital', patient.patient_hospital)

    db.session.commit()
    return jsonify({
        'code': 200,
        'message': '患者信息修改成功！',
        'patient': {
            'id': patient.id,
            'patient_id': patient.patient_id,
            'patient_name': patient.patient_name,
            'patient_sex': patient.patient_sex,
            'patient_age': patient.patient_age,
            'patient_height': patient.patient_height,
            'patient_weight': patient.patient_weight,
            'patient_time': patient.patient_time.strftime('%Y-%m-%d %H:%M'),
            'patient_department': patient.patient_department,
            'patient_type': patient.patient_type,
            'patient_hospital': patient.patient_hospital
        }
    })


# 删除病患
@patient_api.route('/delete/<int:patient_id>', methods=['DELETE'])
def delete_patient(patient_id):
    patient = PatientTable.query.get(patient_id)
    if not patient:
        return jsonify({
            'code': 200,
            'error': '没有找到患者信息！'
        })

    db.session.delete(patient)
    db.session.commit()
    return jsonify({
        'code': 200,
        'message': '患者信息删除成功'}
    )


@patient_api.route('/export_patients', methods=['GET'])
def export_patients():
    patients = PatientTable.query.all()

    # 创建 CSV 文件
    output = StringIO()
    writer = csv.writer(output)

    # 写入标题行
    writer.writerow([
        '病人编号', '名字', '性别', '年龄', '身高', '体重', '患病时间',
        '挂号科室', '疾病类型', '挂号医院'
    ])

    # 写入数据行
    for patient in patients:
        writer.writerow([
            patient.patient_id, patient.patient_name, patient.patient_sex, patient.patient_age,
            patient.patient_height, patient.patient_weight, patient.patient_time.strftime('%Y/%m/%d %H:%M'),
            patient.patient_department, patient.patient_type, patient.patient_hospital
        ])

    # 将 StringIO 对象转换为 bytes
    csv_data = output.getvalue()
    output.close()

    # 创建响应对象
    response = make_response(csv_data)
    response.headers["Content-Disposition"] = "attachment; filename=patients.csv"
    response.headers["Content-Type"] = "text/csv"

    return response


@patient_api.route('/login', methods=['POST'])
def patient_login():
    """
    患者登录接口
    :return:
    """
    if request.method == 'POST':
        account = request.form.get('account')
        password = request.form.get('password')
        if not account or not password:
            return jsonify({'code': 400, 'data': '请输入账号密码'}), 400
        patient = PatientTable.query.filter_by(patient_id=account).first()

        if patient and patient.password == password:
            token = jwt.encode({'user_id': patient.id}, 'secret', algorithm='HS256')
            # 密码正确，创建用户会话或生成认证令牌
            session['user_id'] = patient.id
            # 这里可以返回用户信息或认证令牌
            if isinstance(token, bytes):
                return jsonify(
                    {'code': 200, 'data': {'id': patient.id, 'role': 'patient',
                                           'patient_id': patient.patient_id,
                                           'patient_name': patient.patient_name,
                                           'token': token.decode('utf-8')}})
            else:
                return jsonify({'code': 200, 'data': {'id': patient.id, 'role': 'patient',
                                                      'patient_id': patient.patient_id,
                                                      'patient_name': patient.patient_name,
                                                      'token': token}})
        else:
            # 用户不存在或密码错误
            return jsonify({'code': 400, 'data': '密码或账号错误'})

    # 如果不是POST请求，返回一个提示或重定向
    return jsonify({'code': 405, 'data': '方法不被允许'}), 405
